package org.rainbow.auctionplatform.utils;

import org.quartz.*;
import org.rainbow.auctionplatform.dao.QuartzJobMapper;
import org.rainbow.auctionplatform.model.QuartzJobModel;
import org.rainbow.auctionplatform.service.LotDetailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Component;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

@Component("quartzJobManager")
public class QuartzJobManager {

    private final SchedulerFactoryBean schedulerFactoryBean;

    private final QuartzJobMapper quartzJobMapper;

    private final LotDetailService lotDetailService;

    /** 默认任务组名称 */
    private static final String DEFAULT_JOB_GROUP_NAME = "DefaultJobGroup";
    /** 默认触发器组名称 */
    private static final String DEFAULT_TRIGGER_GROUP_NAME = "DefaultTriggerGroup";

    @Autowired
    public QuartzJobManager(QuartzJobMapper quartzJobMapper, SchedulerFactoryBean schedulerFactoryBean, LotDetailService lotDetailService) {
        this.quartzJobMapper = quartzJobMapper;
        this.schedulerFactoryBean = schedulerFactoryBean;
        this.lotDetailService = lotDetailService;
    }

    /**
     * 加载数据库中已定义的定时任务
     *
     * @Title: loadJobs
     * @Description: 加载数据库中已定义的定时任务
     */
    public void loadJobs() throws SchedulerException {
        List<QuartzJobModel> jobs = quartzJobMapper.getAllJobs();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        long nowTime = new Date().getTime();
        if (null != jobs && !jobs.isEmpty()) {
            for (QuartzJobModel job : jobs) {
                String cronExpression = job.getCronExpression();
                String[] str = cronExpression.split(" ");
                String strDate = str[6] + "-" + str[4] + "-" + str[3] + " " + str[2] + ":" + str[1] + ":" + str[0];
                try {
                    if (nowTime < simpleDateFormat.parse(strDate).getTime()) {
                        // 如果未过期
                        addJob(job, true);
                    } else {// 如果已过期
                        // 删除任务
                        quartzJobMapper.deleteJob(job.getJobName());
                        // 更新tag
                        lotDetailService.updateTag(Integer.valueOf(job.getJobName()));
                    }
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 重新加载数据库中已定义的定时任务
     *
     * @Title: reloadJobs
     * @Description: 重新加载数据库中已定义的定时任务
     */
    public void reloadJobs() throws SchedulerException {
        removeAll();
        loadJobs();
    }

    /**
     * 添加一个新的定时任务
     *
     * @Title: addJob
     * @Description: 添加一个新的定时任务
     * @param job QuartzJobModel
     */
    public void addJob(QuartzJobModel job, boolean isLoad) throws SchedulerException {
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        // 使用"jobName+默认任务组名称"作为定时任务的Key
        Class<?> cls = null;
        try {
            cls = Class.forName(job.getTargetClassName());
            cls.newInstance();
        } catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {
            e.printStackTrace();
        }
        JobDetail jobDetail = JobBuilder
                .newJob((Class<? extends Job>) cls)
                .withIdentity(job.getJobName(), DEFAULT_JOB_GROUP_NAME).build();
        jobDetail.getJobDataMap().put("jobName", job.getJobName());
        // 使用"jobName+默认触发器组名称"作为定时任务触发器的Key
        CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(job.getJobName(), DEFAULT_TRIGGER_GROUP_NAME)
                .startNow()
                .withSchedule(CronScheduleBuilder.cronSchedule(job.getCronExpression()))
                .build();
        scheduler.scheduleJob(jobDetail, trigger);
        if (!scheduler.isShutdown()) {
            scheduler.start();
        }
        job.setJobStatus(scheduler.getTriggerState(new TriggerKey(job.getJobName(), DEFAULT_TRIGGER_GROUP_NAME)).name());
        if (!isLoad) {
            Boolean flag;
            try {
                flag = quartzJobMapper.addJob(job);
            } catch (Exception e) {
                flag = false;
                e.printStackTrace();
            }
            if (!flag) {
                removeJob(job);
            }
        }
    }

    /**
     * 修改定时任务
     *
     * @Title: modifyJob
     * @Description: 修改定时任务
     * @param job QuartzJobModel
     */
    public void modifyJob(QuartzJobModel job) throws SchedulerException {
        removeJob(job);
        addJob(job, false);
    }

    /**
     * 删除定时任务
     *
     * @Title: removeJob
     * @Description: 删除定时任务
     * @param job QuartzJobModel
     */
    public void removeJob(QuartzJobModel job) {
        try {
            Scheduler scheduler = schedulerFactoryBean.getScheduler();
            TriggerKey triggerKey = new TriggerKey(job.getJobName(), DEFAULT_TRIGGER_GROUP_NAME);
            JobKey jobKey = new JobKey(job.getJobName(), DEFAULT_JOB_GROUP_NAME);
            // 根据""暂停触发器
            scheduler.pauseTrigger(triggerKey);
            // 根据""移除触发器
            scheduler.unscheduleJob(triggerKey);
            // 根据""删除定时任务
            scheduler.deleteJob(jobKey);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
        quartzJobMapper.deleteJob(job.getJobName());
    }

    /**
     * 移除所有定时任务
     *
     * @Title: removeAll
     * @Description: 移除所有定时任务
     */
    public void removeAll() {
        List<QuartzJobModel> jobs = quartzJobMapper.getAllJobs();
        if (null != jobs && !jobs.isEmpty()) {
            for (QuartzJobModel job : jobs) {
                removeJob(job);
            }
        }
    }

    /**
     * 暂停定时任务
     *
     * @Title: pauseJob
     * @Description: 暂停定时任务
     * @param job QuartzJobModel
     */
    public void pauseJob(QuartzJobModel job) {
        try {
            Scheduler scheduler = schedulerFactoryBean.getScheduler();
            JobKey jobKey = new JobKey(job.getJobName(), DEFAULT_JOB_GROUP_NAME);
            scheduler.pauseJob(jobKey);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    /**
     * 恢复定时任务
     *
     * @Title: resumeJob
     * @Description: 恢复定时任务
     * @param job QuartzJobModel
     */
    public void resumeJob(QuartzJobModel job) {
        try {
            Scheduler scheduler = schedulerFactoryBean.getScheduler();
            JobKey jobKey = new JobKey(job.getJobName(), DEFAULT_JOB_GROUP_NAME);
            scheduler.resumeJob(jobKey);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    /**
     * 立刻执行一次任务
     *
     * @Title: triggerJob
     * @Description: 立刻执行一次任务
     * @param job QuartzJobModel
     */
    public void triggerJob(QuartzJobModel job) {
        try {
            Scheduler scheduler = schedulerFactoryBean.getScheduler();
            JobKey jobKey = new JobKey(job.getJobName(), DEFAULT_JOB_GROUP_NAME);
            scheduler.triggerJob(jobKey);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }
}
